package microcredit.gui.table;

import java.util.HashMap;
import java.util.Map;

import microcredit.gui.table.impl.GroupTableModel;
import microcredit.gui.table.impl.LoanEntryTableModel;
import microcredit.gui.table.impl.LoanHistoryTableModel;
import microcredit.gui.table.impl.MemberGroupHistoryTableModel;
import microcredit.gui.table.impl.MemberStatusHistoryTableModel;
import microcredit.gui.table.impl.MemberTableModel;
import microcredit.gui.table.impl.MemberToLoanTableModel;
import microcredit.gui.table.impl.MemberToTrainingTypeTableModel;
import microcredit.gui.table.impl.ReportTableModel;
import microcredit.gui.table.impl.TrainingTableModel;
import microcredit.model.Member;
import microcredit.model.MemberGroup;
import microcredit.model.MemberStatusHistory;
import microcredit.model.MemberToGroup;
import microcredit.model.MemberToLoan;
import microcredit.model.MemberToLoanEntry;
import microcredit.model.MemberToLoanHistory;
import microcredit.model.MemberToTrainingType;
import microcredit.model.Report;
import microcredit.model.TrainingType;

public class TableFactory {

	private static Map<Class<?>, Class<?>> mapping = new HashMap<Class<?>, Class<?>>();
	
	static {
		// default table models
		mapping.put(MemberGroup.class, GroupTableModel.class);
		mapping.put(MemberToLoanEntry.class, LoanEntryTableModel.class);
		mapping.put(Member.class, MemberTableModel.class);
		mapping.put(MemberToLoan.class, MemberToLoanTableModel.class);
		mapping.put(MemberToTrainingType.class, MemberToTrainingTypeTableModel.class);
		mapping.put(Report.class, ReportTableModel.class);
		mapping.put(TrainingType.class, TrainingTableModel.class);
		mapping.put(MemberToGroup.class, MemberGroupHistoryTableModel.class);
		mapping.put(MemberStatusHistory.class, MemberStatusHistoryTableModel.class);
		mapping.put(MemberToLoanHistory.class, LoanHistoryTableModel.class);
	}
	
	public static <E> void fill(BeanTable<E> table, Class<E> entityClass, Class<? extends EnumBeanTableModel<E,?>> modelClass) {
		table.setModel(new BeanTableModel<E>(createModel(entityClass, modelClass)));
	}
	
	public static <E> void fill(BeanTable<E> table, Class<E> entityClass) {
		fill(table, entityClass, null);
	}
	
	@SuppressWarnings("unchecked")
	private static <E> EnumBeanTableModel<E, ?> createModel(Class<E> entityClass, Class<? extends EnumBeanTableModel<E, ?>> modelClass) {
		if (modelClass == null) {
			modelClass = (Class<? extends EnumBeanTableModel<E, Enum<?>>>)mapping.get(entityClass);
		}
		
		EnumBeanTableModel<E, ?> enumModel;
		try {
			enumModel = modelClass.newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		} 
		return enumModel;
	}
	
	public static <E> BeanTable<E> create(Class<E> entityClass, Class<? extends EnumBeanTableModel<E, Enum<?>>> modelClass) {
		BeanTable<E> table = new BeanTable<E>();
		fill(table, entityClass, modelClass);
		return table;
	}
	
	public static <E> BeanTable<E> create(Class<E> entityClass) {
		return create(entityClass, null);
	}
	
}
